package com.gzyj.server.nettyserver;

import com.gzyj.server.config.LogConfig;
import com.gzyj.server.config.NettyConfig;
import com.gzyj.server.nettyserver.init.Server808Channel;
import com.gzyj.server.utils.StackUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.NettyRuntime;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


/**
 * @author lhj
 */
@Service
public class Netty808Server {


    @Autowired
    private NettyConfig.NettyServerConfig serverConfig;

    @Autowired
    private Server808Channel server808Channel;

    /**
     * 主链路（服务端）引导入口
     *
     * @throws Exception
     */
    public void runServer() throws Exception {
        //创建主线程池（接收线程池）
        EventLoopGroup boosGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("TCP-server", Thread.MAX_PRIORITY));
        //创建工作线程池
        EventLoopGroup workGroup = new NioEventLoopGroup(NettyRuntime.availableProcessors() + 2, new DefaultThreadFactory("TCP-server", Thread.MAX_PRIORITY));

        try {
            //创建一个服务器端的程序类进行NIO的启动，同时可以设置Channel
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //设置要使用的线程池以及当前的Channel 的类型
            serverBootstrap.group(boosGroup, workGroup);
            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.option(NioChannelOption.SO_REUSEADDR, true);
            serverBootstrap.option(NioChannelOption.SO_BACKLOG, 1024);
            serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
            //接收到的信息处理器
            serverBootstrap.childHandler(server808Channel);
            serverBootstrap.option(ChannelOption.TCP_NODELAY, true);
            serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
            //ChannelFuture描述异步回调的处理操作
            ChannelFuture future = serverBootstrap.bind(serverConfig.getTcpPort()).sync();

            LogConfig.commondLog.info("808网关启动成功 监听端口 {}", serverConfig.getTcpPort());

            future.channel().closeFuture().sync();
        } catch (Exception e) {
            LogConfig.commondErrorLog.error("808网关启动失败 \n {}", StackUtils.getStackInfo(e));
            e.printStackTrace();
        } finally {
            workGroup.shutdownGracefully();
            boosGroup.shutdownGracefully();
        }

    }

}
